设计整套权限控制方案(项目)
设计整套权限控制方案
根据路由动态渲染菜单以及角色权限信息控制按设计按纽级别的显隐-封装V-permission指令
V-permission自定义指令
vue项目实现不同用户角色权限管控:
第一种方式:自定义指令实现用户角色权限控制v-permission:
实现方法:Vue.directive+install+Vue.use
步骤:
- 新建permission.js 实现自定义指令的钩子方法:1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21import store from '@/store'
 export default {
 inserted(el, binding) {
 const { value } = binding
 const roles = store.getters && store.getters.roles
 if (value && value instanceof Array) {
 if (value.length > 0) {
 const permissionRoles = value
 const hasPermission = roles.some(role => {
 return permissionRoles.includes(role)
 })
 if (!hasPermission) {
 el.parentNode && el.parentNode.removeChild(el)
 }
 }
 } else {
 throw new Error(`使用方式: v-permission="['admin','editor']"`)
 }
 }
 }
- 新建index.js 将permission转为install:
| 1 |  | 
- 在main.js中用use方法使用permission:
| 1 |  | 
- 在模板中使用v-permission控制访问权限:
| 1 |  | 
第二种方式:Vue.prototype+install+v-if实现用户角色权限控制:
- 新建permission.js,将checkPer方法注册到Vue.prototype,并注册为install方法:在main.js中引入permission, 并用use方法:1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23import store from '@/store'
 /**
 * @param {Array} value
 * @returns {Boolean}
 * @example see @/views/permission/directive.vue
 */
 export default {
 install(Vue) {
 Vue.prototype.checkPer = (value) => {
 if (value && value instanceof Array && value.length > 0) {
 const roles = store.getters && store.getters.roles
 const permissionRoles = value
 return roles.some(role => {
 return permissionRoles.includes(role)
 })
 } else {
 console.error(`need roles! Like v-permission="['admin','editor']"`)
 return false
 }
 }
 }
 }使用:配合 v-if 在模板中实现权限控制:1 
 2
 3// 权限指令
 import checkPer from '@/utils/permission'
 Vue.use(checkPer)vue权限管控permission实现1 <el-table-column v-if="checkPer(['admin','app:edit','app:del'])" label="操作" width="150px" align="center">vue自定义指令合集之权限校验v-permission在我们日常开发中权限校验是必不可少的一个环节,尤其是对于一些应用系统或一些中后台的开发,更是需要用到权限校验的。那么权限校验也有很多种类,比如菜单权限、组件权限甚至是小到元素权限等等,本文我们就将以元素权限为例,实现一个简单的权限校验自定义指令。 
 在有一些场景中我们可能会根据用户登录后所拥有的权限来决定哪些元素该显示,哪些元素不该显示。比如我们最常使用的就是增删改查操作,那么对于管理员来说权限很大,增删改查都有权限操作,而对于普通用户来说可能只有查询操作,这个时候就需要根据不同用户权限来决定元素的显示和隐藏了。
思路分析
- 首先因为会涉及到元素的展示和隐藏操作,所以在我们自定义指令时就不能再用beforeMount钩子函数了,而是需要用mounted函数,也就是说等元素渲染后再去控制是否展示。
- 在mounted函数中,我们首先需要获取登录用户所拥有的权限。一般情况下在用户登录后会去请求服务器获取用户权限,然后再把权限数据保存在vuex中。这里我们要做的就是把权限数据从vuex中解析出来,便于后续使用。(为了方便展示,我们就直接使用字符串代替了)
- 权限数据拿到以后,我们还需要判断当前元素需要哪些权限,比如删除按钮需要的就是对应的删除权限,而这个权限在元素被定义时就应该已经确定了,所以我们应该在对应的元素中把需要的权限传给我们的自定义指令,然后再通过binding.value拿到该权限
- 最后就是对比校验,看看当前元素所需要的权限是否存在于用户的权限列表中,如果存在则说明有权限元素应该显示,否则没有权限移除对应的元素。
- 以上便是权限自定义指令的整体实现思路,相对来说还是比较简单的,下面我们来看一下具体的代码实现。
 权限校验代码实现1 
 2
 3
 4<button v-permission="'add'">add</button>
 <button v-permission="'del'">del</button>
 <button v-permission="'update'">update</button>
 <button v-permission="'query'">query</button>代码运行起来后,我们会发现对应管理员来说,会看到全部按钮,而对于普通用户来说则只能看到update和query按钮。1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32const app = createApp();
 app.directive('permission',{
 mounted(el,binding){
 //从服务获取用户的权限列表,一般获取后存放于vuex中,本案例为了方便演示将直接以字符串的形式展示
 //权限之间以分号分隔
 //管理员权限:"add;del;update;query"
 //普通用户权限:"add;del;update;query"
 let permission = "update;query",//权限字符串
 permissionList = [];//权限列表
 if(!permission) permission = "";
 permissionList = permission.split(";");
 //获取需要的权限标识,即元素给指令传进来的参数值
 let passText = binding.value,//可以是多个值,中间以分号分隔
 passTextArr = [];//将权限解析到数组中
 if(!passText) passText = "";
 passTextArr = passText.split(';');
 
 //定义一个权限标识变量,用于标识是否有权限
 let flag = false;
 //循环遍历权限列表,检测用户是否有相应的操作权限
 for(let i = 0; i < passTextArr.length; i++){
 if(permissionList.includes(passTextArr[i])){
 //如果从服务器中获取的权限列表中有组件所需的权限,则将flag置为true,同时跳出循环
 flag = true;
 break;
 }
 }
 //如果flag为false,也就是没权限则直接将元素移除或者隐藏
 if(!flag) el.parentNode && el.parentNode.removeChild(el);
 }
 })
首屏看板优化,解决拖拉拽卡顿问题一 渲染优化重新封装组件 重新设计数据 设计vuex持久化存储
vuex数据可持久化-对于刷新也需要保留状态的需要同步到本地存储
多条产品线共享sso单点登录设计
单独提取登录模块 利用cookie 使二级域名可以共卓教据的持点来实现单点登录
涉及到cookie过大超过请求数据量–只保留必须的用户登录信息-token和userinfo至于项目个性信息保存在本地存储
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!